/*
	This file is part of PropExtractor.

	PropExtractor is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	PropExtractor is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with PropExtractor. If not, see <http://www.gnu.org/licenses/>.
*/

#include "PEIncludes.h"

#include "PEAliceSoftAnimation.h"
#include "PETools.h"

namespace pe
{

	int AliceZippedAnimationReadHeader(AliceAnimationZippedHeader* a_Target, PEStream* a_Stream)
	{
		PEStreamRead(a_Stream, a_Target, sizeof(AliceAnimationZippedHeader), 1);

		PE_DEBUG("Zipped header: %s", a_Target->header);

		if (a_Target->header[0] != 'Z' ||
			a_Target->header[1] != 'L' ||
			a_Target->header[2] != 'B')
		{
			return -1;
		}

		return PE_OK;
	}

	int AliceZippedAnimationDecompress(AliceAnimationData* a_Target, AliceAnimationZippedHeader* a_Header, PEStream* a_Stream)
	{
		a_Target->handle = a_Stream;
		a_Target->data = new byte[a_Header->size_uncompressed];
		memset(a_Target->data, 0, a_Header->size_uncompressed);

		byte* data = new byte[a_Header->size_compressed];
		PEStreamRead(a_Stream, data, a_Header->size_compressed, 1);

		uncompress(
			a_Target->data, (unsigned long*)&a_Header->size_uncompressed,
			data, a_Header->size_compressed
		);

		a_Target->header = new AliceAnimationHeader;

		a_Target->data += ReadBytes(a_Target->header, sizeof(AliceAnimationHeader), 1, a_Target->data);
		a_Target->data_total = a_Header->size_uncompressed - sizeof(AliceAnimationHeader);

		return PE_OK;
	}

	int AliceAnimationSaveToFile(AliceAnimationData* a_Data, const char* a_FilePath, const char* a_Pattern /*= NULL*/)
	{
		char path[_MAX_PATH];
		if (strlen(a_FilePath) > 0)
		{
			strcpy(path, a_FilePath);
		}
		else
		{
			sprintf(path, "%s%s.txt", a_Data->handle->dir, a_Data->handle->name);
		}
		
		FILE* handle = fopen(path, "w+b");
		fwrite(a_Data->data - sizeof(AliceAnimationHeader), a_Data->data_total + sizeof(AliceAnimationHeader), 1, handle);

		fclose(handle);

		return PE_OK;
	}

	int AliceAnimationDecrypt(AliceAnimation* a_Target, AliceAnimationData* a_Data)
	{
		a_Target->bone_count = a_Data->header->bones_count;

		PE_DEBUG("Frame count: %i", a_Data->header->bones_count);
		PE_DEBUG("Data count: %i", a_Data->header->data_count);

		byte* read = a_Data->data;

		a_Target->bone = new AliceAnimationBone[a_Target->bone_count];
		AliceAnimationBone* dst = a_Target->bone;

		for (unsigned int i = 0; i < a_Target->bone_count; i++)
		{
			read += ReadUTF8String(&dst->name, read);

			read += ReadBytes(&dst->unknown1, 4, 1, read);
			read += ReadBytes(&dst->padding, 4, 1, read);

			dst->data_count = a_Data->header->data_count;
			dst->data = new AliceAnimationBoneData[dst->data_count];

			read += ReadBytes(dst->data, sizeof(AliceAnimationBoneData), dst->data_count, read);

			PE_DEBUG("Name: %s", dst->name);
			PE_DEBUG("Bone ID: %i", dst->unknown1);
			PE_DEBUG("Padding: %i", dst->padding);

			/*for (float i = 0.f; i < 360.f; i += 0.5f)
			{
				D3DXMATRIX xmat;
				D3DXMatrixIdentity(&xmat);
				D3DXMatrixRotationX(&xmat, i);

				D3DXQUATERNION xquat;
				D3DXQuaternionRotationMatrix(&xquat, &xmat);			

				int bleh = 0;
			}*/

			for (unsigned int i = 0; i < dst->data_count; i++)
			{
				float diff[2] = {
					glm::abs<float>(dst->data[i].unknown[3]) - glm::abs<float>(dst->data[i].unknown[0]),
					glm::abs<float>(dst->data[i].unknown[2]) - glm::abs<float>(dst->data[i].unknown[1])
				};
				
				PE_DEBUG("(%f %f)", diff[0], diff[1]);

				/*float diff[4] = {
					(dst->data[i].unknown[4]) - (dst->data[i].unknown[0]),
					(dst->data[i].unknown[5]) - (dst->data[i].unknown[1]),
					(dst->data[i].unknown[6]) - (dst->data[i].unknown[2]),
					(dst->data[i].unknown[7]) - (dst->data[i].unknown[3])
				};

				PE_DEBUG("(%f %f %f %f)", diff[0], diff[1], diff[2], diff[3]);*/
			}

			glm::gtc::quaternion::quat rot(
				dst->data->unknown[0], 
				//dst->data->unknown[1], 
				//dst->data->unknown[2], 
				0.f,
				0.f,
				dst->data->unknown[3]
			);

			glm::detail::tmat4x4<float> mat = glm::gtc::quaternion::mat4_cast(rot);

			/*PE_DEBUG("(%f %f)", dst->data->unknown[0], dst->data->unknown[1]);
			PE_DEBUG("(%f %f)", dst->data->unknown[2], dst->data->unknown[3]);
			PE_DEBUG("(%f %f)", dst->data->unknown[4], dst->data->unknown[5]); 
			PE_DEBUG("(%f %f)", dst->data->unknown[6], dst->data->unknown[7]);*/
			/*for (unsigned int j = 0; j < dst->data_count; j++)
			{
				PE_DEBUG("(%.3f, %.3f, %.3f)", dst->data[j].x, dst->data[j].y, dst->data[j].z);
			}*/

			dst++;
		}

		return PE_OK;
	}

}